package org.ciallo.simplemusicplayer.service;

import android.app.*;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.net.Uri;
import android.os.*;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.ServiceCompat;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.media3.common.*;
import androidx.media3.exoplayer.ExoPlayer;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import org.ciallo.simplemusicplayer.R;
import org.ciallo.simplemusicplayer.activity.PlayerActivity;
import org.ciallo.simplemusicplayer.data.model.Song;
import org.ciallo.simplemusicplayer.data.repository.SongRepository;
import org.ciallo.simplemusicplayer.service.receiver.MediaButtonReceiver;
import org.ciallo.simplemusicplayer.util.Constants;
import timber.log.Timber;

import java.io.File;
import java.lang.reflect.Type;
import java.util.*;

import static org.ciallo.simplemusicplayer.util.Constants.*;

public class MediaPlayerService extends Service implements Player.Listener, AudioManager.OnAudioFocusChangeListener {

    private final IBinder binder = new LocalBinder();
    private ExoPlayer exoPlayer;
    private Song currentSong;

    private static final MutableLiveData<PlaybackInfo> _playbackInfo = new MutableLiveData<>();
    public static LiveData<PlaybackInfo> playbackInfo = _playbackInfo;

    private AudioManager audioManager;
    // AudioFocusRequest 主要由 ExoPlayer 内部管理，但 Service 作为 Listener 可能需要它
    private AudioFocusRequest audioFocusRequestOreo; // 用于 API 26+

    private PowerManager.WakeLock wakeLock;
    private Handler progressHandler = new Handler(Looper.getMainLooper());
    private Runnable progressUpdater;
    private MediaSessionCompat mediaSession;

    // --- 播放队列和模式管理 ---
    private List<Song> originalPlayQueue = new ArrayList<>(); // 原始播放队列
    private List<Song> shuffledPlayQueue = new ArrayList<>(); // 随机播放队列
    private int currentQueueIndex = Constants.INVALID_INDEX; // 当前在活动队列中的索引
    private int currentPlayMode = Constants.PLAY_MODE_ORDER; // 当前播放模式，默认为顺序播放
    private SharedPreferences sharedPreferences; // 用于持久化状态
    private Gson gson = new Gson(); // 用于序列化列表
    private SongRepository songRepository;
    // 随机播放时使用
    private Random random = new Random();

    @Override
    public void onCreate() {
        super.onCreate();
        Timber.d("MediaPlayerService onCreate");
        songRepository = new SongRepository((Application) getApplicationContext());
        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        sharedPreferences = getSharedPreferences(Constants.PREF_NAME, Context.MODE_PRIVATE); // 初始化 SharedPreferences
        initializePlayer();
        initializeWakeLock();
        initializeMediaSession(); // 初始化媒体会话
        loadPlaybackStateFromPrefs(); // 加载上次的播放状态和队列
        // --- 正确计算初始的 activeQueue ---
        List<Song> initialActiveQueue;
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && shuffledPlayQueue != null && !shuffledPlayQueue.isEmpty()) { // 添加 shuffledPlayQueue != null 的检查
            initialActiveQueue = new ArrayList<>(shuffledPlayQueue); // 使用恢复的随机队列副本
        } else if (originalPlayQueue != null) { // 确保 originalPlayQueue 不是 null
            initialActiveQueue = new ArrayList<>(originalPlayQueue); // 使用恢复的原始队列副本
        } else {
            initialActiveQueue = new ArrayList<>(); // 如果两者都为空或null，则为空列表
        }
        Timber.d("MediaPlayerService onCreate: Initial activeQueue size determined as: %d", initialActiveQueue.size());
        if (!initialActiveQueue.isEmpty()){
            Timber.d("MediaPlayerService onCreate: First song in initialActiveQueue: %s", initialActiveQueue.get(0).getTitle());
        }

        // 使用包含 activeQueue 的构造函数来 post 初始值
        _playbackInfo.postValue(new PlaybackInfo(
                currentSong, // currentSong 也是在 loadPlaybackStateFromPrefs() 中恢复的
                exoPlayer != null && exoPlayer.isPlaying(),
                exoPlayer != null ? exoPlayer.getCurrentPosition() : 0,
                exoPlayer != null && exoPlayer.getDuration() > 0 ? exoPlayer.getDuration() : (currentSong != null ? currentSong.getDuration() : 0), // 确保 duration > 0
                null, // errorMessage
                currentPlayMode,
                initialActiveQueue // <--- 传递正确的初始 activeQueue
        ));
        Timber.d("MediaPlayerService onCreate: Posted initial PlaybackInfo with activeQueue size: %d. Current song: %s",
                initialActiveQueue.size(), (currentSong != null ? currentSong.getTitle() : "null"));

        progressUpdater = () -> {
            if (exoPlayer != null && exoPlayer.isPlaying()) {
                updateCurrentPlaybackInfo();
            }
            // 将每秒更新改为更细粒度，比如200ms，以便进度条更平滑
            progressHandler.postDelayed(progressUpdater, 500);
        };
        // 在服务创建时，让Service成为AudioManager的焦点监听者，主要用于调试或特定需求
        // ExoPlayer的AudioFocusManager也会做自己的监听和处理
        // 为了调试，我们可以保留这个监听，看看焦点变化。
        // 如果确定ExoPlayer的处理完全足够，可以考虑不让Service直接监听。
        // 但为了捕获如永久丢失焦点并停止服务等场景，保留监听可能有用。
        // 重点：不要在这里主动请求焦点，ExoPlayer的play()会做。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            audioFocusRequestOreo = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
                    .setAudioAttributes(new android.media.AudioAttributes.Builder()
                            .setUsage(android.media.AudioAttributes.USAGE_MEDIA)
                            .setContentType(android.media.AudioAttributes.CONTENT_TYPE_MUSIC)
                            .build())
                    .setAcceptsDelayedFocusGain(true)
                    .setOnAudioFocusChangeListener(this)
                    .build();
        }
    }

    private void initializePlayer() {
        if (exoPlayer == null) {
            exoPlayer = new ExoPlayer.Builder(this).build();
            exoPlayer.addListener(this);
            AudioAttributes audioAttributes = new AudioAttributes.Builder()
                    .setUsage(C.USAGE_MEDIA)
                    .setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
                    .build();
            // 关键：第二个参数为 true，让 ExoPlayer 自动管理音频焦点
            exoPlayer.setAudioAttributes(audioAttributes, true);
            exoPlayer.setHandleAudioBecomingNoisy(true);
        }
    }

    private void initializeWakeLock() {
        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        if (powerManager != null) {
            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SimpleMusicPlayer::ServiceWakeLock");
            wakeLock.setReferenceCounted(false);
        } else {
            Timber.e("PowerManager not available, cannot create WakeLock.");
        }
    }

    /**
     * 初始化 MediaSessionCompat。
     * MediaSession 用于与系统媒体控件（如锁屏、通知栏、蓝牙耳机按钮）交互。
     */
    private void initializeMediaSession() {
        ComponentName mediaButtonReceiver = new ComponentName(getApplicationContext(), MediaButtonReceiver.class);
        mediaSession = new MediaSessionCompat(getApplicationContext(), "SimpleMusicPlayerMediaSession", mediaButtonReceiver, null);

        mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

        // 设置 MediaSession 的回调
        mediaSession.setCallback(new MediaSessionCompat.Callback() {
            @Override
            public void onPlay() {
                Timber.d("MediaSession: onPlay triggered.");
                // 如果当前有歌曲并且播放器没有在播放，则开始播放
                // PlayerController 和 UI 层的 togglePlayPause/playNewSong 会更细致地处理播放逻辑，
                // MediaSession 的 onPlay 通常用于从一个非播放状态（例如通知栏点击播放）启动。
                if (exoPlayer != null && currentSong != null) {
                    if (!exoPlayer.isPlaying()) {
                        exoPlayer.play(); // ExoPlayer 会处理音频焦点
                    }
                    // 如果已经是播放状态，或者 currentSong 为 null，则可能不需要额外操作
                    // 或者，如果希望 onPlay 总是尝试从头播放当前歌曲或队列的第一首，可以在这里添加逻辑
                } else if (currentSong == null && !originalPlayQueue.isEmpty()) {
                    // 如果没有当前歌曲但队列不为空，尝试播放队列的第一首
                    Timber.d("MediaSession: onPlay, no current song, playing first from queue.");
                    playSongAtIndex(0, true); // 播放原始队列的第一首
                } else {
                    Timber.w("MediaSession: onPlay, but no current song or queue to play.");
                }
            }

            @Override
            public void onPause() {
                Timber.d("MediaSession: onPause triggered.");
                if (exoPlayer != null && exoPlayer.isPlaying()) {
                    exoPlayer.pause();
                }
            }

            @Override
            public void onSkipToNext() {
                Timber.d("MediaSession: onSkipToNext triggered.");
                // 调用 Service 内部处理下一首的方法
                playNextSongInternal(true); // true 表示这是一个用户操作
            }

            @Override
            public void onSkipToPrevious() {
                Timber.d("MediaSession: onSkipToPrevious triggered.");
                // 调用 Service 内部处理上一首的方法
                playPreviousSongInternal(true); // true 表示这是一个用户操作
            }

            @Override
            public void onStop() {
                Timber.d("MediaSession: onStop triggered.");
                // 停止播放并准备停止服务
                stopPlaybackAndService(); // 调用我们之前定义的停止方法
            }

            @Override
            public void onSeekTo(long pos) {
                Timber.d("MediaSession: onSeekTo %d", pos);
                seekTo(pos); // 调用 Service 内部的 seekTo 方法
            }
        });
        // 你可以根据需要覆盖更多 MediaSessionCompat.Callback 的方法，
        // 例如 onSetRepeatMode, onSetShuffleModeEnabled 等，
        // 并将它们连接到 MediaPlayerService 内部对应的播放模式设置逻辑。
        // 例如:
            /*
            @Override
            public void onSetRepeatMode(int repeatMode) {
                Timber.d("MediaSession: onSetRepeatMode %d", repeatMode);
                // 将 PlaybackStateCompat 的 repeatMode 转换为我们自己的 PLAY_MODE_*
                // PlaybackStateCompat.REPEAT_MODE_NONE -> PLAY_MODE_ORDER 或 PLAY_MODE_LIST_LOOP (取决于不循环时的行为)
                // PlaybackStateCompat.REPEAT_MODE_ONE -> PLAY_MODE_SINGLE_LOOP
                // PlaybackStateCompat.REPEAT_MODE_ALL -> PLAY_MODE_LIST_LOOP
                // PlaybackStateCompat.REPEAT_MODE_GROUP (不常用)
                int newPlayMode;
                switch (repeatMode) {
                    case PlaybackStateCompat.REPEAT_MODE_ONE:
                        newPlayMode = Constants.PLAY_MODE_SINGLE_LOOP;
                        break;
                    case PlaybackStateCompat.REPEAT_MODE_ALL:
                        newPlayMode = Constants.PLAY_MODE_LIST_LOOP;
                        break;
                    case PlaybackStateCompat.REPEAT_MODE_NONE:
                    default:
                        newPlayMode = Constants.PLAY_MODE_ORDER; // 或者根据你的默认行为
                        break;
                }
                setPlayModeInternal(newPlayMode);
            }

            @Override
            public void onSetShuffleMode(@PlaybackStateCompat.ShuffleMode int shuffleMode) {
                Timber.d("MediaSession: onSetShuffleMode %d", shuffleMode);
                if (shuffleMode == PlaybackStateCompat.SHUFFLE_MODE_ALL || shuffleMode == PlaybackStateCompat.SHUFFLE_MODE_GROUP) {
                    setPlayModeInternal(Constants.PLAY_MODE_SHUFFLE);
                } else if (shuffleMode == PlaybackStateCompat.SHUFFLE_MODE_NONE) {
                    // 如果当前是随机模式，则切换回顺序模式（或上一个非随机模式）
                    if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
                        setPlayModeInternal(Constants.PLAY_MODE_ORDER);
                    }
                }
            }
            */
        mediaSession.setActive(true); // 激活 MediaSession
    }

    private void acquireWakeLock() {
        if (wakeLock != null && !wakeLock.isHeld()) {
            wakeLock.acquire(10 * 60 * 1000L);
            Timber.d("WakeLock acquired");
        }
    }

    private void releaseWakeLock() {
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
            Timber.d("WakeLock released");
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null || intent.getAction() == null) {
            Timber.w("onStartCommand received null intent or action, returning START_NOT_STICKY");
            // 如果服务被系统杀死并重启，intent可能为空。此时应尝试恢复上次状态。
            if (currentSong == null && !originalPlayQueue.isEmpty() && currentQueueIndex != INVALID_INDEX) {
                Timber.i("Service restarted, attempting to resume last playback state.");
                playSongAtIndex(currentQueueIndex, false); // 尝试播放上次的歌曲，但不强制开始播放
            }
            return START_STICKY; // 确保服务在被杀死后能重启
        }

        String action = intent.getAction();
        Timber.d("MediaPlayerService onStartCommand, action: %s", action);

        switch (action) {
            // 使用新的 ACTION_PLAY_SONG_AT_INDEX 作为主要播放入口
            case ACTION_PLAY_SONG_AT_INDEX:
                List<Song> queue = intent.getParcelableArrayListExtra(EXTRA_PLAY_QUEUE);
                int startIndex = intent.getIntExtra(EXTRA_START_INDEX, 0);
                if (queue != null && !queue.isEmpty()) {
                    setPlayQueueInternal(queue, startIndex, true); // true 表示立即播放
                } else if (intent.hasExtra(EXTRA_SONG_OBJECT)) { // 兼容旧的只播放单曲的ACTION_PLAY_SONG逻辑
                    Song songToPlay = intent.getParcelableExtra(EXTRA_SONG_OBJECT);
                    if (songToPlay != null) {
                        setPlayQueueInternal(Collections.singletonList(songToPlay), 0, true);
                    }
                } else {
                    Timber.w("ACTION_PLAY_SONG_AT_INDEX without queue or song object.");
                }
                break;
            // 可选：如果只想更新队列而不立即播放
            case ACTION_SET_PLAY_QUEUE:
                List<Song> newQueue = intent.getParcelableArrayListExtra(EXTRA_PLAY_QUEUE);
                int newStartIndex = intent.getIntExtra(EXTRA_START_INDEX, currentQueueIndex); // 默认保持当前索引
                if (newQueue != null) {
                    setPlayQueueInternal(newQueue, newStartIndex, false); // false 表示不立即强制播放
                }
                break;
            case ACTION_TOGGLE_PLAY_PAUSE:
                togglePlayPause();
                break;
            case ACTION_SEEK_TO:
                long position = intent.getLongExtra(EXTRA_SEEK_POSITION, 0);
                seekTo(position);
                break;
            case ACTION_NEXT_SONG:
                playNextSongInternal(true); // true 表示用户手动触发
                break;
            case ACTION_PREVIOUS_SONG:
                playPreviousSongInternal(true); // true 表示用户手动触发
                break;
            case ACTION_SET_PLAY_MODE:
                int mode = intent.getIntExtra(EXTRA_PLAY_MODE, Constants.PLAY_MODE_ORDER);
                setPlayModeInternal(mode);
                break;
            case ACTION_REMOVE_SONG_FROM_QUEUE:
                long songIdToRemove = intent.getLongExtra(EXTRA_SONG_ID_TO_REMOVE, -1);
                if (songIdToRemove != -1) {
                    removeSongFromQueueInternal(songIdToRemove);
                }
                break;
            case ACTION_CLEAR_QUEUE:
                clearQueueInternal();
                break;
            case ACTION_STOP_SERVICE:
                stopPlaybackAndService();
                break;
            case ACTION_PLAY_SPECIFIC_SONG_ID_IN_QUEUE: // <--- 新增 case
                long songIdToPlay = intent.getLongExtra(Constants.EXTRA_SONG_ID, -1);
                if (songIdToPlay != -1) {
                    playSpecificSongByIdInQueueInternal(songIdToPlay);
                } else {
                    Timber.w("ACTION_PLAY_SPECIFIC_SONG_ID_IN_QUEUE received without a valid song ID.");
                }
                break;
            case Constants.ACTION_PLAY_IMMEDIATELY:
                Song songToPlayImmediately = intent.getParcelableExtra(Constants.EXTRA_SONG_OBJECT);
                if (songToPlayImmediately != null) {
                    playImmediatelyInternal(songToPlayImmediately);
                } else {
                    Timber.w("ACTION_PLAY_IMMEDIATELY received without a song object.");
                }
                break;

            case Constants.ACTION_INSERT_SONG_AS_NEXT_IN_QUEUE:
                Song songToInsertNext = intent.getParcelableExtra(Constants.EXTRA_SONG_OBJECT);
                if (songToInsertNext != null) {
                    insertSongAsNextInternal(songToInsertNext, false); // false for playImmediately unless queue was empty
                } else {
                    Timber.w("ACTION_INSERT_SONG_AS_NEXT_IN_QUEUE received without a song object.");
                }
                break;

            case Constants.ACTION_ADD_SONG_TO_END_OF_QUEUE:
                Song songToAddToEnd = intent.getParcelableExtra(Constants.EXTRA_SONG_OBJECT);
                if (songToAddToEnd != null) {
                    addSongToEndOfQueueInternal(songToAddToEnd, false); // false for playImmediately unless queue was empty
                } else {
                    Timber.w("ACTION_ADD_SONG_TO_END_OF_QUEUE received without a song object.");
                }
                break;
            default:
                Timber.w("Unknown action received: %s", action);
                // 处理媒体按钮转发的Intent (如果配置了MediaButtonReceiver)
                MediaButtonReceiver.handleIntent(mediaSession, intent);
                break;
        }
        return START_STICKY;
    }

    /**
     * 内部方法：将歌曲添加到播放队列的末尾。
     * @param songToInsert      要添加的歌曲。
     * @param playNowIfQueueEmpty 如果队列之前为空，是否立即播放。
     */
    private void addSongToEndOfQueueInternal(Song songToInsert, boolean playNowIfQueueEmpty) {
        if (songToInsert == null) return;
        Timber.d("addSongToEndOfQueueInternal called for song: %s", songToInsert.getTitle());

        boolean wasEmptyOrNoCurrentSong = originalPlayQueue.isEmpty() || currentSong == null || currentQueueIndex == Constants.INVALID_INDEX;

        // 1. 从原始队列和随机队列中移除此歌的任何现有实例
        originalPlayQueue.removeIf(s -> s.getId() == songToInsert.getId());
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            shuffledPlayQueue.removeIf(s -> s.getId() == songToInsert.getId());
        }

        // 2. 添加到 originalPlayQueue 末尾
        originalPlayQueue.add(songToInsert);

        // 3. 如果是随机模式，重新生成随机队列
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            generateShuffledQueue(true); // 尝试保留 currentSong
            // 更新 currentQueueIndex (同 insertSongAsNextInternal 中的逻辑)
            if (currentSong != null) {
                int newIdx = findSongIndexInList(shuffledPlayQueue, currentSong.getId());
                if(newIdx != Constants.INVALID_INDEX) currentQueueIndex = newIdx;
                else if (!shuffledPlayQueue.isEmpty()) currentQueueIndex = 0;
                else currentQueueIndex = Constants.INVALID_INDEX;
            } else if (!shuffledPlayQueue.isEmpty()) {
                currentQueueIndex = 0;
            } else {
                currentQueueIndex = Constants.INVALID_INDEX;
            }
        }
        // 对于非随机模式，currentQueueIndex 仍然指向原来的 currentSong

        Timber.i("Song '%s' added to end of queue. Original queue size: %d", songToInsert.getTitle(), originalPlayQueue.size());

        // 4. 如果队列之前为空或没有当前歌曲，并且 playNowIfQueueEmpty 为 true，则播放
        if ((wasEmptyOrNoCurrentSong || !isPlayerActive()) && playNowIfQueueEmpty) {
            Timber.d("Queue was empty or player inactive, playing the added song now.");
            List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !shuffledPlayQueue.isEmpty()) ? shuffledPlayQueue : originalPlayQueue;
            int playIndex = findSongIndexInList(activeQueue, songToInsert.getId());
            if(playIndex != Constants.INVALID_INDEX){
                playSongAtIndex(playIndex, true);
            } else if (!activeQueue.isEmpty()){
                playSongAtIndex(0, true);
            }
        } else {
            updateCurrentPlaybackInfo();
        }
        saveQueueStateToPrefs();
    }

    // 辅助方法：检查播放器是否处于活动状态 (非空闲/错误/停止)
    private boolean isPlayerActive() {
        if (exoPlayer == null) return false;
        int state = exoPlayer.getPlaybackState();
        return state != Player.STATE_IDLE && state != Player.STATE_ENDED;
    }

    // 辅助方法：在列表中查找歌曲的索引
    private int findSongIndexInList(List<Song> queue, long songId) {
        if (queue == null || songId == Constants.INVALID_INDEX) return Constants.INVALID_INDEX;
        for (int i = 0; i < queue.size(); i++) {
            if (queue.get(i).getId() == songId) {
                return i;
            }
        }
        return Constants.INVALID_INDEX;
    }

    /**
     * 内部方法：将歌曲插入到当前播放歌曲的“下一首”位置。
     * @param songToInsert      要插入的歌曲。
     * @param playNowIfQueueEmpty 如果队列之前为空，是否立即播放。
     */
    private void insertSongAsNextInternal(Song songToInsert, boolean playNowIfQueueEmpty) {
        if (songToInsert == null) return;
        Timber.d("insertSongAsNextInternal called for song: %s", songToInsert.getTitle());

        boolean wasEmptyOrNoCurrentSong = originalPlayQueue.isEmpty() || currentSong == null || currentQueueIndex == Constants.INVALID_INDEX;

        // 1. 从原始队列和随机队列中移除此歌的任何现有实例
        originalPlayQueue.removeIf(s -> s.getId() == songToInsert.getId());
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            shuffledPlayQueue.removeIf(s -> s.getId() == songToInsert.getId());
        }

        // 2. 确定在 originalPlayQueue 中的插入位置
        int insertAtIndexOriginal;
        if (wasEmptyOrNoCurrentSong) {
            insertAtIndexOriginal = 0;
        } else {
            int currentOriginalSongIndex = findSongIndexInList(originalPlayQueue, currentSong.getId());
            insertAtIndexOriginal = (currentOriginalSongIndex != Constants.INVALID_INDEX)
                    ? currentOriginalSongIndex + 1
                    : (originalPlayQueue.isEmpty() ? 0 : currentQueueIndex + 1); // 插入到当前播放索引之后
            if (insertAtIndexOriginal > originalPlayQueue.size()) { // 防止越界
                insertAtIndexOriginal = originalPlayQueue.size();
            }
        }
        originalPlayQueue.add(insertAtIndexOriginal, songToInsert);

        // 3. 如果是随机模式，重新生成随机队列
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            // 保持 currentSong (如果它还在 originalPlayQueue 中) 的概念，
            // 并在生成随机队列时尝试保留它。新插入的歌也会参与随机。
            generateShuffledQueue(true);
            // 更新 currentQueueIndex 以指向旧的 currentSong 在新随机队列中的位置
            if (currentSong != null) {
                int newIdx = findSongIndexInList(shuffledPlayQueue, currentSong.getId());
                if(newIdx != Constants.INVALID_INDEX) currentQueueIndex = newIdx;
                else if (!shuffledPlayQueue.isEmpty()) currentQueueIndex = 0; // currentSong 可能已被替换
                else currentQueueIndex = Constants.INVALID_INDEX;
            } else if (!shuffledPlayQueue.isEmpty()) {
                currentQueueIndex = 0; // 如果之前没有currentSong，指向新的随机队列开头
            } else {
                currentQueueIndex = Constants.INVALID_INDEX;
            }
        }
        // 对于非随机模式，currentQueueIndex 仍然指向原来的 currentSong，除非 originalPlayQueue 为空

        Timber.i("Song '%s' inserted as next. Original queue size: %d", songToInsert.getTitle(), originalPlayQueue.size());

        // 4. 如果队列之前为空或没有当前歌曲，并且 playNowIfQueueEmpty 为 true，则播放
        if ((wasEmptyOrNoCurrentSong || !isPlayerActive()) && playNowIfQueueEmpty) {
            Timber.d("Queue was empty or player inactive, playing the inserted song now.");
            // 找到新插入的歌在当前活动队列中的索引并播放
            List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !shuffledPlayQueue.isEmpty()) ? shuffledPlayQueue : originalPlayQueue;
            int playIndex = findSongIndexInList(activeQueue, songToInsert.getId());

            if(playIndex != Constants.INVALID_INDEX){
                playSongAtIndex(playIndex, true); // 播放这首歌
            } else if (!activeQueue.isEmpty()){
                playSongAtIndex(0, true); // 回退到播放队列第一首
            }
        } else {
            // 否则，只更新播放信息（主要是队列变了）
            updateCurrentPlaybackInfo();
        }
        saveQueueStateToPrefs();
    }

    /**
     * 内部方法：将歌曲插入到当前播放歌曲的“前面一位”并立即播放。
     * 如果当前没有歌曲播放，则作为第一首播放。
     * 如果歌曲已在队列中，先移除旧的。
     * @param songToPlay 准备立即播放的歌曲。
     */
    private void playImmediatelyInternal(Song songToPlay) {
        if (songToPlay == null) return;
        Timber.d("playImmediatelyInternal called for song: %s", songToPlay.getTitle());

        // 1. 从原始播放队列中移除此歌的任何现有实例
        originalPlayQueue.removeIf(s -> s.getId() == songToPlay.getId());
        // 如果是随机模式，也从随机队列中移除 (如果它能从ID匹配到)
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            shuffledPlayQueue.removeIf(s -> s.getId() == songToPlay.getId());
        }

        // 2. 确定在 originalPlayQueue 中的插入位置
        int insertAtIndexOriginal;
        if (currentSong == null || originalPlayQueue.isEmpty() || currentQueueIndex == Constants.INVALID_INDEX) {
            // 没有当前歌曲或队列为空，插入到开头
            insertAtIndexOriginal = 0;
        } else {
            // 找到当前歌曲在 originalPlayQueue 中的位置
            int currentOriginalSongIndexInOriginalQueue = findSongIndexInList(originalPlayQueue, currentSong.getId());
            insertAtIndexOriginal = (currentOriginalSongIndexInOriginalQueue != Constants.INVALID_INDEX)
                    ? currentOriginalSongIndexInOriginalQueue // 插入到当前歌曲的位置，它将被替换
                    : currentQueueIndex; // 使用 currentQueueIndex 作为备选（通常指向活动队列）
            if (insertAtIndexOriginal < 0 || insertAtIndexOriginal > originalPlayQueue.size()) { // 确保插入位置有效
                insertAtIndexOriginal = 0; // 如果索引无效，则插入到开头
            }
        }
        originalPlayQueue.add(insertAtIndexOriginal, songToPlay);

        // 3. 如果是随机模式，需要重新生成随机队列，并尝试将新播放的歌置于当前播放位置
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            this.currentSong = songToPlay; // 明确将要播放的歌曲设为 currentSong
            generateShuffledQueue(true); // true 会尝试将 currentSong 放到随机队列的开头或合适位置
            // 找到新currentSong在shuffledPlayQueue中的位置
            this.currentQueueIndex = findSongIndexInList(shuffledPlayQueue, this.currentSong.getId());
            if(this.currentQueueIndex == Constants.INVALID_INDEX && !shuffledPlayQueue.isEmpty()){
                this.currentQueueIndex = 0; // 以防万一
            }
        } else {
            // 对于非随机模式，currentQueueIndex 就是 insertAtIndexOriginal
            this.currentQueueIndex = insertAtIndexOriginal;
        }

        // 4. 设置为当前歌曲并立即播放
        this.currentSong = songToPlay;
        playGivenSong(this.currentSong); // playGivenSong会处理播放

        saveQueueStateToPrefs();
        updateCurrentPlaybackInfo();
        Timber.i("Song '%s' set to play immediately. New original queue size: %d", songToPlay.getTitle(), originalPlayQueue.size());
    }


    /**
     * 在当前活动的播放队列中查找指定ID的歌曲并开始播放。
     * 此方法不会改变原始播放队列的内容或顺序，仅更新当前播放的歌曲和索引。
     *
     * @param songIdToPlay 要播放的歌曲的ID。
     */
    private void playSpecificSongByIdInQueueInternal(long songIdToPlay) {
        List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !shuffledPlayQueue.isEmpty())
                ? shuffledPlayQueue
                : originalPlayQueue;

        if (activeQueue.isEmpty()) {
            Timber.w("Cannot play song ID %d: Active queue is empty.", songIdToPlay);
            return;
        }

        int foundIndex = Constants.INVALID_INDEX;
        Song songToPlay = null;

        for (int i = 0; i < activeQueue.size(); i++) {
            if (activeQueue.get(i).getId() == songIdToPlay) {
                songToPlay = activeQueue.get(i);
                foundIndex = i;
                break;
            }
        }

        if (songToPlay != null && foundIndex != Constants.INVALID_INDEX) {
            Timber.d("Found song ID %d at index %d in active queue. Playing now.", songIdToPlay, foundIndex);
            this.currentSong = songToPlay; // 更新当前歌曲
            this.currentQueueIndex = foundIndex; // 更新当前在活动队列中的索引

            playGivenSong(this.currentSong); // 调用已有的播放方法
            // playGivenSong 内部会处理 ExoPlayer 的 setMediaItem, prepare, play 和 updateMediaSessionMetadata
            // 并且 onIsPlayingChanged 会处理 wakeLock, progressUpdater, 通知和状态保存

            saveCurrentSongStateToPrefs(); // 确保保存新的当前歌曲状态
            updateCurrentPlaybackInfo(); // 立即更新一次 LiveData
        } else {
            Timber.w("Song ID %d not found in the current active queue. Cannot play.", songIdToPlay);
            // 可以选择发送一个错误信息到UI，或者不执行任何操作
            // _playbackInfo.postValue(new PlaybackInfo(... an error message ...));
        }
    }

    public void playGivenSong(Song song) {
        if (song == null || song.getPath() == null || song.getPath().isEmpty()) {
            Timber.e("playGivenSong: Song or path is null/empty.");
            _playbackInfo.postValue(new PlaybackInfo(currentSong, false, 0, 0, "无效的歌曲对象或路径"));
            return;
        }
        this.currentSong = song;
        Timber.i("playGivenSong: Attempting to play song: %s, Path: %s", currentSong.getTitle(), currentSong.getPath());
        try {
            Uri songUri = Uri.fromFile(new File(currentSong.getPath()));
            Timber.d("playGivenSong: Song URI: %s", songUri.toString());
            MediaItem mediaItem = MediaItem.fromUri(songUri);
            Timber.d("playGivenSong: MediaItem created.");
            if (exoPlayer == null) {
                Timber.e("playGivenSong: ExoPlayer is NULL before setMediaItem!");
                initializePlayer(); // 尝试重新初始化，但不应该在这里发生
                if (exoPlayer == null) {
                    Timber.e("playGivenSong: ExoPlayer still NULL after re-init! Aborting.");
                    _playbackInfo.postValue(new PlaybackInfo(currentSong, false, 0, 0, "播放器初始化失败"));
                    return;
                }
            }
            exoPlayer.setMediaItem(mediaItem);
            Timber.d("playGivenSong: MediaItem set to ExoPlayer.");
            exoPlayer.prepare();
            Timber.d("playGivenSong: ExoPlayer prepared.");
            exoPlayer.play();
            Timber.d("playGivenSong: ExoPlayer.play() called.");
            // 记录到最近播放
            if (songRepository != null && currentSong != null) {
                songRepository.addOrUpdateRecentPlay(currentSong.getId());
            }

            // 增加播放次数
            if (songRepository != null && currentSong != null) {
                songRepository.incrementPlayCount(currentSong.getId()); // <--- 新增调用
            }

            updateMediaSessionMetadata();
        } catch (Exception e) {
            Timber.e(e, "playGivenSong: Error preparing or playing song: %s", currentSong.getPath());
            Timber.e(e, "Error preparing or playing song: %s", currentSong.getPath());
            _playbackInfo.postValue(new PlaybackInfo(currentSong, false, 0, 0, "播放准备失败: " + e.getMessage(), currentPlayMode, getCurrentActiveQueueSnapshot()));
            releaseWakeLock();
        }
    }

    // 辅助方法获取当前活动队列的快照 (与 PlaybackInfo 中的逻辑一致)
    private List<Song> getCurrentActiveQueueSnapshot() {
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !shuffledPlayQueue.isEmpty()) {
            return new ArrayList<>(shuffledPlayQueue);
        } else {
            return new ArrayList<>(originalPlayQueue);
        }
    }

    public void togglePlayPause() {
        if (exoPlayer == null) {
            Timber.e("ExoPlayer is null, cannot toggle play/pause.");
            return;
        }
        if (exoPlayer.getPlayWhenReady()) { // 使用 getPlayWhenReady() 更准确判断意图是否为播放
            exoPlayer.pause(); // 如果打算播放，则暂停
            // releaseWakeLock(); // WakeLock的释放在 onIsPlayingChanged(false) 中处理
        } else {
            if (currentSong != null) {
                exoPlayer.play(); // ExoPlayer 会自动请求焦点
                // acquireWakeLock(); // WakeLock的获取在 onIsPlayingChanged(true) 中处理
            } else {
                Timber.w("No current song to play/resume.");
                _playbackInfo.postValue(new PlaybackInfo(null, false, 0, 0, "没有可播放的歌曲"));
            }
        }
    }

    public void seekTo(long positionMs) {
        if (exoPlayer != null && currentSong != null) {
            if (positionMs < 0) positionMs = 0;
            if (positionMs > exoPlayer.getDuration() && exoPlayer.getDuration() > 0) {
                positionMs = exoPlayer.getDuration();
            }
            exoPlayer.seekTo(positionMs);
            // updateCurrentPlaybackInfo(); // ExoPlayer 状态改变会通过 Listener 更新，这里不需要立即更新
        } else {
            Timber.w("ExoPlayer is null or no current song, cannot seek.");
        }
    }

    /**
     * 更新并广播当前的播放信息 (歌曲、播放状态、进度、时长、播放模式、活动队列)。
     */
    private void updateCurrentPlaybackInfo() {
        if (exoPlayer == null && currentSong == null && originalPlayQueue.isEmpty()) {
            // 只有在完全没有状态时才发送初始空状态
            PlaybackInfo lastInfo = _playbackInfo.getValue();
            if (lastInfo == null || lastInfo.song != null || lastInfo.isPlaying || (lastInfo.activeQueue != null && !lastInfo.activeQueue.isEmpty())) {
                _playbackInfo.postValue(new PlaybackInfo(null, false, 0, 0, null, currentPlayMode, Collections.emptyList()));
            }
            return;
        }

        long currentPosition = 0;
        long duration = 0;
        boolean isPlaying = false;

        if (exoPlayer != null) {
            currentPosition = exoPlayer.getCurrentPosition();
            duration = exoPlayer.getDuration();
            isPlaying = exoPlayer.isPlaying();
        }


        // 如果ExoPlayer报告的duration无效(C.TIME_UNSET或0)，并且我们有歌曲对象，则使用歌曲对象的时长
        if ((duration == C.TIME_UNSET || duration <= 0) && currentSong != null && currentSong.getDuration() > 0) {
            duration = currentSong.getDuration();
        }
        // 确保 currentPosition 不会超过 duration
        if (duration > 0 && currentPosition > duration) {
            currentPosition = duration;
        }

        // 确定当前活动的播放队列
        List<Song> activeQueue;
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !shuffledPlayQueue.isEmpty()) {
            activeQueue = new ArrayList<>(shuffledPlayQueue); // 返回副本
        } else {
            activeQueue = new ArrayList<>(originalPlayQueue); // 返回副本
        }


        Timber.d("updateCurrentPlaybackInfo: Calculated activeQueue size: %d", activeQueue.size());
        PlaybackInfo newInfo = new PlaybackInfo(
                currentSong,
                isPlaying,
                currentPosition,
                duration,
                null, // 正常播放时错误信息为null
                currentPlayMode, // 包含当前播放模式
                activeQueue // 传递当前活动的播放队列
        );

        Timber.d("updateCurrentPlaybackInfo: Posting PlaybackInfo with activeQueue size: %d. First song if any: %s",
                newInfo.activeQueue.size(),
                newInfo.activeQueue.isEmpty() ? "N/A" : newInfo.activeQueue.get(0).getTitle());
        _playbackInfo.postValue(newInfo);
    }


    /**
     * Player.Listener Callbacks
     */
    @Override
    public void onIsPlayingChanged(boolean isPlaying) {
        Timber.d("SERVICE: ExoPlayer onIsPlayingChanged: %s", isPlaying);
        updateCurrentPlaybackInfo();
        updateMediaSessionPlaybackState();

        if (isPlaying) {
            acquireWakeLock();
            progressHandler.removeCallbacks(progressUpdater);
            progressHandler.post(progressUpdater);
            startForegroundWithNotification();
            saveCurrentSongStateToPrefs(); // 播放开始时保存状态
        } else {
            progressHandler.removeCallbacks(progressUpdater);
            releaseWakeLock();
            if (exoPlayer != null && exoPlayer.getPlaybackState() != Player.STATE_IDLE) {
                updateNotification();
            }
            // 如果是因为播放完成而暂停 (STATE_ENDED 会处理下一首)
            // 或者是用户手动暂停，也保存一下状态
            if (exoPlayer != null && (exoPlayer.getPlaybackState() == Player.STATE_READY || exoPlayer.getPlaybackState() == Player.STATE_BUFFERING)) {
                saveCurrentSongStateToPrefs();
            }
        }
    }

    @Override
    public void onPlaybackStateChanged(int playbackState) {
        Timber.d("SERVICE: ExoPlayer onPlaybackStateChanged: %d", playbackState);
        updateCurrentPlaybackInfo();
        updateMediaSessionPlaybackState();

        switch (playbackState) {
            case Player.STATE_IDLE:
                releaseWakeLock();
                ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
                break;
            case Player.STATE_ENDED:
                Timber.i("SERVICE: Playback has ended for song: %s", (currentSong != null ? currentSong.getTitle() : "N/A"));
                // 播放完成后，根据播放模式决定下一步
                playNextSongInternal(false); // false 表示非用户手动触发
                break;
            case Player.STATE_READY:
                if (!exoPlayer.getPlayWhenReady()) {
                    releaseWakeLock();
                    updateNotification();
                }
                break;
        }
    }

    @Override
    public void onMediaItemTransition(@Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason) {
        // 当ExoPlayer内部的MediaItem切换时调用
        // 我们的逻辑是手动通过playSongAtIndex切换歌曲和MediaItem，
        // 所以这个回调主要是为了确保我们的currentSong与ExoPlayer的当前项一致（如果ExoPlayer有自己的播放列表行为）
        // 或者在播放列表模式下，当ExoPlayer自动播放下一项时，我们需要更新我们的currentSong和currentQueueIndex
        Timber.d("SERVICE: onMediaItemTransition, new MediaItem: %s, reason: %d", (mediaItem != null ? mediaItem.mediaId : "null"), reason);

        if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_AUTO ||
                reason == Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED && mediaItem != null) {
            // 如果是ExoPlayer自动切换（例如，如果ExoPlayer被配置为列表播放且有自己的队列）
            // 我们需要找到这个新的 mediaItem 对应的 Song 对象，并更新我们的 currentSong 和 currentQueueIndex
            // 这部分逻辑取决于我们如何给ExoPlayer设置播放列表。
            // 当前我们是 setMediaItem 单个播放，然后手动管理下一首。
            // 所以，这个回调更多是用于观察，除非我们改变了ExoPlayer的播放列表管理方式。
            // 如果我们手动调用了 playNextSongInternal() 等，currentSong 应该已经被更新了。
            // 这里主要是确保 MediaSession 元数据更新
            updateMediaSessionMetadata(); // 确保MediaSession使用最新的歌曲信息
        }
        // saveCurrentSongStateToPrefs(); // 歌曲切换时保存状态，由playSongAtIndex等方法处理更佳
    }


    @Override
    public void onPlayerError(@NonNull PlaybackException error) {
        Timber.e(error, "SERVICE: ExoPlayer encountered an error. Code: %s, Message: %s, Type: %d, RendererIndex: %d, TimestampMs: %d",
                error.getErrorCodeName(),
                error.getMessage(),
                error.timestampMs);
        if (error.getCause() != null) {
            Timber.e(error.getCause(), "SERVICE: ExoPlayer error cause");
        }
        Timber.e(error, "SERVICE: ExoPlayer encountered an error");
        String errorMessage = "播放器错误: " + error.getErrorCodeName();
        _playbackInfo.postValue(new PlaybackInfo(
                currentSong, false,
                exoPlayer != null ? exoPlayer.getCurrentPosition() : 0,
                exoPlayer != null && exoPlayer.getDuration() > 0 ? exoPlayer.getDuration() : (currentSong != null ? currentSong.getDuration() : 0),
                errorMessage
        ));
        releaseWakeLock();
        ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE); // 出错时移除前台和通知
        // 考虑是否 stopSelf()
    }


    @Override
    public void onAudioFocusChange(int focusChange) {
        // 这个回调主要用于调试或处理 ExoPlayer 自动行为之外的特殊情况。
        // ExoPlayer 的 AudioFocusManager 会处理暂停/恢复/降低音量等。
        Timber.d("SERVICE: AudioManager onAudioFocusChange in Service: %d", focusChange);
        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                Timber.i("SERVICE: Audio focus GAINED.");
                // ExoPlayer应该会自动恢复或开始播放（如果之前是短暂丢失）
                break;
            case AudioManager.AUDIOFOCUS_LOSS:
                Timber.w("SERVICE: Audio focus LOST (permanent). ExoPlayer should have paused/stopped.");
                // 你可以在这里决定是否停止服务
                // stopSelf();
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                Timber.w("SERVICE: Audio focus LOST (transient). ExoPlayer should have paused.");
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                Timber.i("SERVICE: Audio focus LOST (transient, can duck). ExoPlayer should have ducked.");
                break;
            default:
                Timber.d("SERVICE: Unknown audio focus state: %d", focusChange);
        }
        // 理论上不需要在此处调用 updateCurrentPlaybackInfo()，因为ExoPlayer状态变化会通过Player.Listener回调
    }

    /**
     * 更新 MediaSession 的元数据 (歌曲信息、封面等)。
     */
    private void updateMediaSessionMetadata() {
        if (currentSong == null || mediaSession == null) {
            // 清除元数据或设置默认值
            if (mediaSession != null) {
                mediaSession.setMetadata(new MediaMetadataCompat.Builder()
                        .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "无歌曲")
                        .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, 0)
                        .build());
            }
            return;
        }

        MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder()
                .putString(MediaMetadataCompat.METADATA_KEY_TITLE, currentSong.getTitle())
                .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, currentSong.getArtistName())
                .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, currentSong.getAlbumName())
                .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, currentSong.getDuration());

        // 异步加载封面并设置到MediaSession
        if (currentSong.getAlbumArtUri() != null && !currentSong.getAlbumArtUri().isEmpty()) {
            Glide.with(this)
                    .asBitmap()
                    .load(Uri.parse(currentSong.getAlbumArtUri()))
                    .into(new CustomTarget<Bitmap>() {
                        @Override
                        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                            metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, resource);
                            mediaSession.setMetadata(metadataBuilder.build());
                        }

                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                            mediaSession.setMetadata(metadataBuilder.build()); // 无封面也更新
                        }

                        @Override
                        public void onLoadFailed(@Nullable Drawable errorDrawable) {
                            // 尝试加载内嵌封面 (如果SongMetadataUtil可用)
                            // Bitmap embedded = SongMetadataUtil.getEmbeddedPicture(currentSong.getPath());
                            // if(embedded != null) metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, embedded);
                            mediaSession.setMetadata(metadataBuilder.build());
                        }
                    });
        } else {
            // Bitmap embedded = SongMetadataUtil.getEmbeddedPicture(currentSong.getPath());
            // if(embedded != null) metadataBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, embedded);
            mediaSession.setMetadata(metadataBuilder.build()); // 如果URI为空，尝试内嵌或无封面
        }
    }

    /**
     * 更新 MediaSession 的播放状态 (播放/暂停/缓冲等)。
     */
    private void updateMediaSessionPlaybackState() {
        if (mediaSession == null || exoPlayer == null) return;

        PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder()
                .setActions(
                        PlaybackStateCompat.ACTION_PLAY |
                                PlaybackStateCompat.ACTION_PLAY_PAUSE |
                                PlaybackStateCompat.ACTION_PAUSE |
                                PlaybackStateCompat.ACTION_SEEK_TO |
                                PlaybackStateCompat.ACTION_SKIP_TO_NEXT | // 即使未实现，也声明能力
                                PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | // 同上
                                PlaybackStateCompat.ACTION_STOP
                );

        int exoPlayerState = exoPlayer.getPlaybackState();
        boolean isPlaying = exoPlayer.isPlaying();
        int sessionState;

        if (exoPlayerState == Player.STATE_IDLE || exoPlayerState == Player.STATE_ENDED) {
            sessionState = PlaybackStateCompat.STATE_STOPPED;
        } else if (exoPlayerState == Player.STATE_BUFFERING) {
            sessionState = PlaybackStateCompat.STATE_BUFFERING;
        } else if (isPlaying) {
            sessionState = PlaybackStateCompat.STATE_PLAYING;
        } else {
            sessionState = PlaybackStateCompat.STATE_PAUSED;
        }

        stateBuilder.setState(sessionState, exoPlayer.getCurrentPosition(), 1.0f); // 播放速度1.0f
        mediaSession.setPlaybackState(stateBuilder.build());
    }

    /**
     * 创建通知渠道 (Android O及以上版本需要)。
     */
    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    NOTIFICATION_CHANNEL_ID,
                    NOTIFICATION_CHANNEL_NAME,
                    NotificationManager.IMPORTANCE_LOW // 低优先级，避免声音和振动
            );
            serviceChannel.setDescription("音乐播放控制通知");
            serviceChannel.setSound(null, null); // 无声音
            serviceChannel.enableLights(false);
            serviceChannel.enableVibration(false);
            serviceChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);

            NotificationManager manager = getSystemService(NotificationManager.class);
            if (manager != null) {
                manager.createNotificationChannel(serviceChannel);
            }
        }
    }

    /**
     * 将服务置于前台并显示通知。
     */
    private void startForegroundWithNotification() {
        createNotificationChannel();
        Notification notification = buildPlayerNotification();
        if (notification != null) {
            int foregroundServiceType = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                foregroundServiceType = android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
            }
            ServiceCompat.startForeground(this, NOTIFICATION_ID_PLAYER, notification, foregroundServiceType);
            Timber.d("Service started in foreground with notification.");
        } else {
            Timber.w("Could not build notification, service not started in foreground.");
        }
    }

    /**
     * 更新现有通知。
     */
    private void updateNotification() {
        Notification notification = buildPlayerNotification();
        if (notification != null) {
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (notificationManager != null) {
                notificationManager.notify(NOTIFICATION_ID_PLAYER, notification);
                Timber.d("Notification updated.");
            }
        }
    }

    /**
     * 构建播放器通知。
     *
     * @return 构建好的 Notification 对象，如果无法构建则返回 null (例如 currentSong 为 null)。
     */
    private Notification buildPlayerNotification() {
        if (currentSong == null) {
            Timber.w("Cannot build notification: currentSong is null.");
            return null; // 没有歌曲时，不应显示播放通知
        }

        boolean isPlaying = exoPlayer != null && exoPlayer.isPlaying();

        // 点击通知主体跳转到 PlayerActivity
        Intent contentIntent = new Intent(this, PlayerActivity.class);
        PendingIntent contentPendingIntent = PendingIntent.getActivity(this, 0, contentIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0));

        // 播放/暂停 Action
        Intent playPauseIntent = new Intent(this, MediaPlayerService.class).setAction(ACTION_TOGGLE_PLAY_PAUSE);
        PendingIntent playPausePendingIntent = PendingIntent.getService(this, 1, playPauseIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0));

        // 下一首 Action
        Intent nextIntent = new Intent(this, MediaPlayerService.class).setAction(ACTION_NEXT_SONG);
        PendingIntent nextPendingIntent = PendingIntent.getService(this, 2, nextIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0));

        // 上一首 Action
        Intent prevIntent = new Intent(this, MediaPlayerService.class).setAction(ACTION_PREVIOUS_SONG);
        PendingIntent prevPendingIntent = PendingIntent.getService(this, 3, prevIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0));

        // 停止服务 Action (用于滑动清除通知时)
        Intent stopIntent = new Intent(this, MediaPlayerService.class).setAction(ACTION_STOP_SERVICE);
        PendingIntent stopPendingIntent = PendingIntent.getService(this, 4, stopIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0));


        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setContentTitle(currentSong.getTitle())
                .setContentText(currentSong.getArtistName())
                .setSmallIcon(R.drawable.ic_notification_music_note) // 确保这个drawable存在
                .setContentIntent(contentPendingIntent) // 点击通知主体
                .setDeleteIntent(stopPendingIntent)     // 滑动清除通知时发送的Intent
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setOngoing(isPlaying) // 正在播放时通知不可清除
                // 添加媒体控制按钮
                .addAction(R.drawable.ic_notification_skip_previous, "上一首", prevPendingIntent)
                .addAction(isPlaying ? R.drawable.ic_notification_pause : R.drawable.ic_notification_play,
                        isPlaying ? "暂停" : "播放", playPausePendingIntent)
                .addAction(R.drawable.ic_notification_skip_next, "下一首", nextPendingIntent)
                // 使用 MediaStyle
                .setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
                                .setMediaSession(mediaSession.getSessionToken()) // 关联MediaSession
                                .setShowActionsInCompactView(0, 1, 2) // 在紧凑视图中显示哪些按钮 (索引)
                        // .setShowCancelButton(true) // 如果想要一个明确的关闭按钮
                        // .setCancelButtonIntent(stopPendingIntent)
                );

        // 异步加载封面并设置到通知
        if (currentSong.getAlbumArtUri() != null && !currentSong.getAlbumArtUri().isEmpty()) {
            Glide.with(this)
                    .asBitmap()
                    .load(Uri.parse(currentSong.getAlbumArtUri()))
                    .into(new CustomTarget<Bitmap>(128, 128) { // 指定一个合理的大小
                        @Override
                        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                            builder.setLargeIcon(resource);
                            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                            if (nm != null) nm.notify(NOTIFICATION_ID_PLAYER, builder.build());
                        }

                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                        }

                        @Override
                        public void onLoadFailed(@Nullable Drawable errorDrawable) {
                            // Bitmap embedded = SongMetadataUtil.getEmbeddedPicture(currentSong.getPath());
                            // if(embedded != null) builder.setLargeIcon(embedded);
                            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                            if (nm != null) nm.notify(NOTIFICATION_ID_PLAYER, builder.build()); // 即使封面加载失败也更新通知
                        }
                    });
        } else {
            // 如果没有封面URI，可以尝试加载内嵌封面或不设置大图标
            // Bitmap embedded = SongMetadataUtil.getEmbeddedPicture(currentSong.getPath());
            // if(embedded != null) builder.setLargeIcon(embedded);
        }
        return builder.build();
    }

    /**
     * 设置新的播放队列，并可选择是否立即开始播放。
     *
     * @param newQueue        新的歌曲列表。
     * @param startIndex      开始播放的索引。
     * @param playImmediately 是否立即开始播放指定索引的歌曲。
     */
    private void setPlayQueueInternal(List<Song> newQueue, int startIndex, boolean playImmediately) {
        Timber.d("MediaPlayerService.setPlayQueueInternal: Received newQueue size: %d, startIndex: %d, playImmediately: %b",
                (newQueue != null ? newQueue.size() : 0), startIndex, playImmediately);
        if (newQueue == null || newQueue.isEmpty()) {
            Timber.w("setPlayQueueInternal called with null or empty queue.");
            clearQueueInternal(); // 如果新队列为空，则清空当前队列并停止
            return;
        }

        this.originalPlayQueue = new ArrayList<>(newQueue); // 创建副本
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            generateShuffledQueue(true); // true 表示如果当前歌曲在新队列中，尝试保持它
        }

        // 校验 startIndex
        if (startIndex < 0 || startIndex >= this.originalPlayQueue.size()) {
            Timber.w("Invalid startIndex %d for queue size %d. Defaulting to 0.", startIndex, this.originalPlayQueue.size());
            startIndex = 0;
        }

        // 如果不是随机播放，或者随机播放但未指定特殊处理，currentQueueIndex 直接对应原始队列的 startIndex
        // 如果是随机播放，并且我们希望从随机队列的特定位置开始（例如，保持当前歌曲），则需要额外逻辑
        // 为简单起见，这里假设随机模式下，如果playImmediately为true，则从随机队列的第一个有效歌曲开始
        // 或者，如果 generateShuffledQueue(true) 成功保持了 currentSong，则 currentQueueIndex 会被正确设置。

        if (playImmediately) {
            // 根据当前播放模式和 startIndex 确定实际要播放的歌曲及其在活动队列中的索引
            if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
                if (!shuffledPlayQueue.isEmpty()) {
                    // 尝试在随机队列中找到 startIndex 对应的原始歌曲，或直接播放随机队列的第一个
                    Song songToStartWith = originalPlayQueue.get(startIndex);
                    int actualShuffleIndex = INVALID_INDEX;
                    for (int i = 0; i < shuffledPlayQueue.size(); i++) {
                        if (shuffledPlayQueue.get(i).getId() == songToStartWith.getId()) {
                            actualShuffleIndex = i;
                            break;
                        }
                    }
                    if (actualShuffleIndex != INVALID_INDEX) {
                        playSongAtIndex(actualShuffleIndex, true);
                    } else {
                        playSongAtIndex(0, true); // 播放随机队列的第一个
                    }
                } else {
                    Timber.w("Shuffled queue is empty after generation, cannot play immediately.");
                    clearQueueInternal();
                }
            } else {
                playSongAtIndex(startIndex, true); // 直接播放原始队列的指定索引
            }
        } else {
            // 只更新队列，不立即播放，但需要更新 currentSong 和 currentQueueIndex (如果它们改变了)
            // 找到 startIndex 对应的歌曲
            Song potentialCurrentSong = originalPlayQueue.get(startIndex);
            boolean songChanged = (currentSong == null || currentSong.getId() != potentialCurrentSong.getId());

            if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
                // 在随机模式下，即使不立即播放，也要确定 currentQueueIndex
                // 找到 potentialCurrentSong 在 shuffledPlayQueue 中的位置
                int shuffleIndex = INVALID_INDEX;
                if (!shuffledPlayQueue.isEmpty()) {
                    for (int i = 0; i < shuffledPlayQueue.size(); i++) {
                        if (shuffledPlayQueue.get(i).getId() == potentialCurrentSong.getId()) {
                            shuffleIndex = i;
                            break;
                        }
                    }
                }
                this.currentQueueIndex = (shuffleIndex != INVALID_INDEX) ? shuffleIndex : 0;
            } else {
                this.currentQueueIndex = startIndex;
            }
            this.currentSong = originalPlayQueue.get(this.currentQueueIndex < originalPlayQueue.size() ? this.currentQueueIndex : 0);


            if (songChanged && exoPlayer != null) { // 如果歌曲变了，需要为ExoPlayer准备新歌，但不播放
                Uri songUri = Uri.fromFile(new File(this.currentSong.getPath()));
                MediaItem mediaItem = MediaItem.fromUri(songUri);
                exoPlayer.setMediaItem(mediaItem);
                exoPlayer.prepare(); // 准备但不播放
                exoPlayer.seekTo(0); // 重置到开头
                updateMediaSessionMetadata();
            }
            updateCurrentPlaybackInfo(); // 更新状态，isPlaying 应该是 false
        }
        saveQueueStateToPrefs();
        Timber.d("Play queue set. Original size: %d, Shuffled size: %d, Start index: %d, Play mode: %d",
                originalPlayQueue.size(), shuffledPlayQueue.size(), this.currentQueueIndex, currentPlayMode);
    }


    /**
     * 播放指定索引的歌曲。索引是相对于当前活动队列的。
     *
     * @param index     歌曲在活动队列中的索引。
     * @param forcePlay 是否强制开始播放（即使播放器当前是暂停状态）。
     */
    private void playSongAtIndex(int index, boolean forcePlay) {
        List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) ? shuffledPlayQueue : originalPlayQueue;

        if (activeQueue.isEmpty() || index < 0 || index >= activeQueue.size()) {
            Timber.w("Invalid index or empty queue for playSongAtIndex. Index: %d, ActiveQueue size: %d", index, activeQueue.size());
            stopPlaybackAndServiceIfNeeded(); // 如果队列无效，则停止
            return;
        }

        currentQueueIndex = index; // 更新当前在活动队列中的索引
        Song songToPlay = activeQueue.get(currentQueueIndex);
        playGivenSong(songToPlay); // playGivenSong 会处理播放逻辑

        if (forcePlay && exoPlayer != null && !exoPlayer.isPlaying()) {
            exoPlayer.play();
        }
        saveCurrentSongStateToPrefs(); // 保存当前播放的歌曲ID和索引
    }


    /**
     * 生成随机播放队列。
     *
     * @param保守 当前歌曲（如果存在且在新队列中）应该尝试保留在随机队列的某个位置（通常是第一个）。
     */
    private void generateShuffledQueue(boolean keepCurrentSongIfPossible) {
        if (originalPlayQueue.isEmpty()) {
            shuffledPlayQueue = new ArrayList<>();
            return;
        }
        shuffledPlayQueue = new ArrayList<>(originalPlayQueue);
        Song songToPreserve = null;

        if (keepCurrentSongIfPossible && currentSong != null) {
            // 检查当前歌曲是否仍在新的 originalPlayQueue 中
            boolean currentSongExistsInNewQueue = false;
            for (Song s : originalPlayQueue) {
                if (s.getId() == currentSong.getId()) {
                    currentSongExistsInNewQueue = true;
                    songToPreserve = s; // 使用新队列中的实例
                    break;
                }
            }
            if (!currentSongExistsInNewQueue) {
                songToPreserve = null; // 当前歌曲不在新队列了，无法保留
            }
        }

        Collections.shuffle(shuffledPlayQueue, random);

        if (songToPreserve != null) {
            // 将要保留的歌曲移到随机队列的开头
            shuffledPlayQueue.remove(songToPreserve); // 先移除（如果存在多个相同ID的歌曲，这可能不完美）
            shuffledPlayQueue.add(0, songToPreserve);
            currentQueueIndex = 0; // 如果保留了歌曲并放在开头，更新索引
            currentSong = songToPreserve; // 确保 currentSong 指向的是队列中的实例
        }
        Timber.d("Generated shuffled queue. Size: %d. Kept current song: %s", shuffledPlayQueue.size(), (songToPreserve != null));
    }


    /**
     * 播放下一首歌曲，根据当前播放模式。
     *
     * @param byUserAction 是否由用户手动触发（例如点击按钮），影响单曲循环模式的行为。
     */
    private void playNextSongInternal(boolean byUserAction) {
        List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) ? shuffledPlayQueue : originalPlayQueue;
        if (activeQueue.isEmpty()) {
            Timber.w("PlayNext: Active queue is empty.");
            stopPlaybackAndServiceIfNeeded();
            return;
        }

        if (currentPlayMode == Constants.PLAY_MODE_SINGLE_LOOP && !byUserAction) {
            Timber.d("PlayNext: Single loop mode, replaying current song.");
            seekTo(0); // 重播当前歌曲
            if (exoPlayer != null && !exoPlayer.isPlaying()) exoPlayer.play();
            return;
        }

        currentQueueIndex++;
        if (currentQueueIndex >= activeQueue.size()) {
            if (currentPlayMode == Constants.PLAY_MODE_LIST_LOOP || (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !originalPlayQueue.isEmpty())) {
                currentQueueIndex = 0; // 列表循环或随机播放完一轮后从头开始
                if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
                    generateShuffledQueue(false); // 重新生成随机队列，不特意保留当前歌曲
                    activeQueue = shuffledPlayQueue; // 更新活动队列引用
                    if (activeQueue.isEmpty()) { // 再次检查，以防原始队列变空
                        stopPlaybackAndServiceIfNeeded();
                        return;
                    }
                }
            } else if (currentPlayMode == Constants.PLAY_MODE_ORDER) {
                Timber.i("PlayNext: Reached end of queue in order mode. Stopping playback.");
                stopPlaybackAndServiceIfNeeded(); // 顺序播放到末尾则停止
                return;
            } else { // PLAY_MODE_SINGLE_LOOP 但由用户触发，或者其他意外情况
                currentQueueIndex = 0; // 默认行为：循环到开头
            }
        }
        if (currentQueueIndex >= activeQueue.size())
            currentQueueIndex = activeQueue.isEmpty() ? INVALID_INDEX : 0; // 再次安全检查

        if (currentQueueIndex != INVALID_INDEX) {
            playSongAtIndex(currentQueueIndex, true);
        } else {
            stopPlaybackAndServiceIfNeeded();
        }
    }

    /**
     * 播放上一首歌曲，根据当前播放模式。
     *
     * @param byUserAction 是否由用户手动触发。
     */
    private void playPreviousSongInternal(boolean byUserAction) {
        List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) ? shuffledPlayQueue : originalPlayQueue;
        if (activeQueue.isEmpty()) {
            Timber.w("PlayPrevious: Active queue is empty.");
            stopPlaybackAndServiceIfNeeded();
            return;
        }

        // 如果当前播放进度超过阈值（例如3秒），则重新播放当前歌曲，否则播放上一首
        if (exoPlayer != null && exoPlayer.getCurrentPosition() > 3000 && currentQueueIndex != INVALID_INDEX) {
            Timber.d("PlayPrevious: Current song played for >3s, replaying.");
            seekTo(0);
            if (!exoPlayer.isPlaying()) exoPlayer.play();
            return;
        }

        currentQueueIndex--;
        if (currentQueueIndex < 0) {
            if (currentPlayMode == Constants.PLAY_MODE_LIST_LOOP || currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
                currentQueueIndex = activeQueue.size() - 1; // 循环到末尾
                if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !originalPlayQueue.isEmpty()) {
                    // 随机模式下，播放上一首通常是播放随机列表的前一首，
                    // 如果到了开头再跳到末尾，可能需要重新生成一个“反向”的随机序列，或只是简单循环当前随机列表
                    // 这里简单处理为循环当前随机列表
                }
            } else if (currentPlayMode == Constants.PLAY_MODE_ORDER) {
                Timber.i("PlayPrevious: Reached start of queue in order mode. Stopping or playing last.");
                currentQueueIndex = activeQueue.size() - 1; // 顺序播放到头，可以停止或循环到末尾，这里选择循环到末尾
                // stopPlaybackAndServiceIfNeeded(); // 或者停止
                // return;
            } else { // PLAY_MODE_SINGLE_LOOP 但由用户触发
                currentQueueIndex = activeQueue.size() - 1; // 默认行为：循环到末尾
            }
        }
        if (currentQueueIndex < 0 && !activeQueue.isEmpty()) currentQueueIndex = 0; // 防止size为0或1时出现-1

        if (currentQueueIndex != INVALID_INDEX && currentQueueIndex < activeQueue.size()) {
            playSongAtIndex(currentQueueIndex, true);
        } else {
            stopPlaybackAndServiceIfNeeded();
        }
    }

    /**
     * 设置新的播放模式。
     *
     * @param newMode 新的播放模式常量。
     */
    private void setPlayModeInternal(int newMode) {
        if (currentPlayMode == newMode) return;

        currentPlayMode = newMode;
        Timber.d("Play mode set to: %d", currentPlayMode);

        // 根据新模式调整队列和索引
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            generateShuffledQueue(true); // 切换到随机时，尝试保留当前歌曲
            // currentQueueIndex 应该在 generateShuffledQueue 中被更新（如果歌曲被保留并置于首位）
            // 或者如果当前歌曲不在新生成的随机队列中，可以选择播放随机队列的第一个
            // 这里我们假设 generateShuffledQueue(true) 会将 currentSong 放到 shuffledPlayQueue[0]
            // 并且 playSongAtIndex 会被调用或UI会反映这个变化
        } else {
            // 从随机模式切换回其他模式，需要将 currentQueueIndex 映射回 originalPlayQueue
            if (currentSong != null && !originalPlayQueue.isEmpty()) {
                int originalIndex = INVALID_INDEX;
                for (int i = 0; i < originalPlayQueue.size(); i++) {
                    if (originalPlayQueue.get(i).getId() == currentSong.getId()) {
                        originalIndex = i;
                        break;
                    }
                }
                if (originalIndex != INVALID_INDEX) {
                    currentQueueIndex = originalIndex;
                } else {
                    // 当前歌曲不在原始播放列表了 (例如列表已更新)，则可能需要停止或播放第一首
                    currentQueueIndex = originalPlayQueue.isEmpty() ? INVALID_INDEX : 0;
                    currentSong = (currentQueueIndex != INVALID_INDEX) ? originalPlayQueue.get(currentQueueIndex) : null;
                    // 如果 currentSong 变了，需要更新播放器，但不立即播放
                    if (exoPlayer != null && currentSong != null) {
                        Uri songUri = Uri.fromFile(new File(currentSong.getPath()));
                        MediaItem mediaItem = MediaItem.fromUri(songUri);
                        exoPlayer.setMediaItem(mediaItem);
                        exoPlayer.prepare();
                        exoPlayer.seekTo(0);
                        updateMediaSessionMetadata();
                    } else if (currentSong == null) {
                        stopPlaybackAndServiceIfNeeded();
                    }
                }
            } else { // 没有当前歌曲或原始队列为空
                currentQueueIndex = INVALID_INDEX;
                currentSong = null;
                stopPlaybackAndServiceIfNeeded();
            }
        }
        updateCurrentPlaybackInfo(); // 包含新的播放模式
        savePlaybackModeToPrefs();
    }

    /**
     * 从播放队列中移除指定的歌曲。
     *
     * @param songIdToRemove 要移除的歌曲ID。
     */
    private void removeSongFromQueueInternal(long songIdToRemove) {
        boolean removedFromOriginal = false;
        int originalIndexRemoved = -1;
        Song nextSongToPlay = null;

        // 1. 从原始队列移除
        for (int i = 0; i < originalPlayQueue.size(); i++) {
            if (originalPlayQueue.get(i).getId() == songIdToRemove) {
                originalPlayQueue.remove(i);
                removedFromOriginal = true;
                originalIndexRemoved = i;
                break;
            }
        }

        // 2. 如果是随机模式，也从随机队列移除，并可能需要重新生成或调整
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            boolean removedFromShuffled = false;
            for (int i = 0; i < shuffledPlayQueue.size(); i++) {
                if (shuffledPlayQueue.get(i).getId() == songIdToRemove) {
                    shuffledPlayQueue.remove(i);
                    removedFromShuffled = true;
                    break;
                }
            }
            // 如果随机队列因此变空，但原始队列还有歌，重新生成随机队列
            if (shuffledPlayQueue.isEmpty() && !originalPlayQueue.isEmpty()) {
                generateShuffledQueue(false); // 不保留当前歌曲，因为可能就是它被删了
            }
        }

        if (removedFromOriginal) {
            Timber.d("Song ID %d removed from queue(s).", songIdToRemove);
            // 3. 处理当前播放状态
            if (currentSong != null && currentSong.getId() == songIdToRemove) { // 如果删除的是当前播放的歌曲
                Timber.d("Removed current playing song.");
                List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) ? shuffledPlayQueue : originalPlayQueue;
                if (!activeQueue.isEmpty()) {
                    // 尝试播放下一首（根据当前索引位置，如果删除后该位置仍有效）
                    // 如果 originalIndexRemoved 是当前播放的歌在原始队列的索引
                    // currentQueueIndex 是在活动队列的索引
                    // 这里逻辑会比较复杂，取决于 currentQueueIndex 的维护方式
                    // 简单处理：如果当前歌曲被删除，尝试播放活动队列中的下一首（如果存在）或第一首
                    currentQueueIndex = (originalIndexRemoved < activeQueue.size()) ? originalIndexRemoved : 0;
                    if (currentQueueIndex >= activeQueue.size()) currentQueueIndex = 0; // 确保不越界
                    playSongAtIndex(currentQueueIndex, exoPlayer.getPlayWhenReady()); // 保持之前的播放状态
                } else {
                    stopPlaybackAndServiceIfNeeded(); // 队列空了，停止
                }
            } else if (currentSong != null) { // 如果删除的不是当前歌曲
                // 更新当前歌曲在活动队列中的索引 (如果需要)
                List<Song> activeQueue = (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) ? shuffledPlayQueue : originalPlayQueue;
                int newCurrentPlayingActualIndex = INVALID_INDEX;
                for (int i = 0; i < activeQueue.size(); i++) {
                    if (activeQueue.get(i).getId() == currentSong.getId()) {
                        newCurrentPlayingActualIndex = i;
                        break;
                    }
                }
                if (newCurrentPlayingActualIndex != INVALID_INDEX) {
                    currentQueueIndex = newCurrentPlayingActualIndex;
                } else {
                    // 当前播放的歌曲不在活动队列了（不太可能发生，除非队列逻辑有误）
                    // 停止或播放第一首
                    currentQueueIndex = activeQueue.isEmpty() ? INVALID_INDEX : 0;
                    playSongAtIndex(currentQueueIndex, exoPlayer.getPlayWhenReady());
                }
            }
            saveQueueStateToPrefs();
            updateCurrentPlaybackInfo(); // 更新UI
        }
    }

    /**
     * 清空播放队列。
     */
    private void clearQueueInternal() {
        Timber.d("Clearing play queue.");
        originalPlayQueue.clear();
        shuffledPlayQueue.clear();
        currentSong = null;
        currentQueueIndex = INVALID_INDEX;
        if (exoPlayer != null) {
            exoPlayer.stop(); // 停止播放
            exoPlayer.clearMediaItems(); // 清除播放器的媒体项
        }
        updateCurrentPlaybackInfo(); // UI 更新为空状态
        saveQueueStateToPrefs();
        // 考虑是否也停止前台服务和通知，如果设计是队列清空=无事可做
        // ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
        // stopSelf(); // 如果希望服务也停止
    }

    /**
     * 如果队列为空，则停止播放并可能停止服务（根据设计）。
     */
    private void stopPlaybackAndServiceIfNeeded() {
        if (currentSong == null || ((currentPlayMode == Constants.PLAY_MODE_SHUFFLE) ? shuffledPlayQueue.isEmpty() : originalPlayQueue.isEmpty())) {
            Timber.i("Queue is empty or current song is null, stopping playback and service.");
            if (exoPlayer != null) {
                exoPlayer.stop();
                exoPlayer.clearMediaItems();
            }
            currentSong = null;
            currentQueueIndex = INVALID_INDEX;
            updateCurrentPlaybackInfo();
            // ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
            // stopSelf(); // 根据需要决定是否停止服务
        }
    }

    private void stopPlaybackAndService() {
        if (exoPlayer != null) {
            exoPlayer.stop();
            exoPlayer.clearMediaItems();
        }
        currentSong = null;
        currentQueueIndex = INVALID_INDEX;
        updateCurrentPlaybackInfo();
        ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
        stopSelf();
        Timber.i("Playback and service stopped explicitly.");
    }

    /**
     * 保存当前播放队列、歌曲、模式和位置到SharedPreferences。
     */
    private void saveQueueStateToPrefs() {
        if (sharedPreferences == null) return;
        SharedPreferences.Editor editor = sharedPreferences.edit();

        // 保存原始队列
        String originalQueueJson = gson.toJson(originalPlayQueue);
        editor.putString(Constants.PREF_KEY_ORIGINAL_QUEUE_JSON, originalQueueJson);

        // 如果是随机模式，保存随机队列；否则清除它以避免混淆
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
            String shuffledQueueJson = gson.toJson(shuffledPlayQueue);
            editor.putString(Constants.PREF_KEY_SHUFFLED_QUEUE_JSON, shuffledQueueJson);
        } else {
            editor.remove(Constants.PREF_KEY_SHUFFLED_QUEUE_JSON);
        }
        saveCurrentSongStateToPrefs(); // 单独保存当前歌曲相关状态
        editor.apply();
        Timber.d("Full queue state saved to SharedPreferences.");
    }

    /**
     * 保存当前播放歌曲的ID、在原始队列中的索引、播放模式和播放位置。
     */
    private void saveCurrentSongStateToPrefs() {
        if (sharedPreferences == null) return;
        SharedPreferences.Editor editor = sharedPreferences.edit();
        if (currentSong != null) {
            editor.putLong(Constants.PREF_KEY_CURRENT_SONG_ID, currentSong.getId());
            editor.putLong(Constants.PREF_KEY_LAST_POSITION, exoPlayer != null ? exoPlayer.getCurrentPosition() : 0);

            // 找到当前歌曲在 originalPlayQueue 中的索引并保存
            int originalIndex = INVALID_INDEX;
            for (int i = 0; i < originalPlayQueue.size(); i++) {
                if (originalPlayQueue.get(i).getId() == currentSong.getId()) {
                    originalIndex = i;
                    break;
                }
            }
            editor.putInt(Constants.PREF_KEY_ORIGINAL_QUEUE_INDEX, originalIndex);

        } else {
            editor.remove(Constants.PREF_KEY_CURRENT_SONG_ID);
            editor.remove(Constants.PREF_KEY_LAST_POSITION);
            editor.putInt(Constants.PREF_KEY_ORIGINAL_QUEUE_INDEX, INVALID_INDEX);
        }
        savePlaybackModeToPrefs(); // 播放模式也应随当前歌曲状态保存或独立保存
        editor.apply();
        Timber.d("Current song state saved to SharedPreferences.");
    }


    /**
     * 保存当前播放模式到SharedPreferences。
     */
    private void savePlaybackModeToPrefs() {
        if (sharedPreferences == null) return;
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt(Constants.PREF_KEY_PLAY_MODE, currentPlayMode);
        editor.apply();
        Timber.d("Playback mode saved: %d", currentPlayMode);
    }

    /**
     * 从SharedPreferences加载上次的播放状态（队列、歌曲、模式、位置）。
     */
    private void loadPlaybackStateFromPrefs() {
        if (sharedPreferences == null) return;

        currentPlayMode = sharedPreferences.getInt(Constants.PREF_KEY_PLAY_MODE, Constants.PLAY_MODE_ORDER);
        long lastSongId = sharedPreferences.getLong(Constants.PREF_KEY_CURRENT_SONG_ID, -1);
        long lastPosition = sharedPreferences.getLong(Constants.PREF_KEY_LAST_POSITION, 0);
        int lastOriginalQueueIndex = sharedPreferences.getInt(Constants.PREF_KEY_ORIGINAL_QUEUE_INDEX, INVALID_INDEX);

        Type songListType = new TypeToken<ArrayList<Song>>() {
        }.getType();

        // 加载原始队列
        String originalQueueJson = sharedPreferences.getString(Constants.PREF_KEY_ORIGINAL_QUEUE_JSON, null);
        if (originalQueueJson != null) {
            originalPlayQueue = gson.fromJson(originalQueueJson, songListType);
            if (originalPlayQueue == null) originalPlayQueue = new ArrayList<>();
        } else {
            originalPlayQueue = new ArrayList<>();
        }

        // 如果是随机模式，加载随机队列，否则重新生成
        if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE && !originalPlayQueue.isEmpty()) {
            String shuffledQueueJson = sharedPreferences.getString(Constants.PREF_KEY_SHUFFLED_QUEUE_JSON, null);
            if (shuffledQueueJson != null) {
                shuffledPlayQueue = gson.fromJson(shuffledQueueJson, songListType);
                if (shuffledPlayQueue == null || shuffledPlayQueue.isEmpty()) { // 如果保存的随机队列有问题，重新生成
                    generateShuffledQueue(false);
                }
            } else {
                generateShuffledQueue(false);
            }
        } else {
            shuffledPlayQueue = new ArrayList<>(); // 非随机模式或原始队列为空，则随机队列也为空
        }

        // 恢复当前歌曲和索引
        if (lastSongId != -1 && !originalPlayQueue.isEmpty() && lastOriginalQueueIndex != INVALID_INDEX && lastOriginalQueueIndex < originalPlayQueue.size()) {
            currentSong = originalPlayQueue.get(lastOriginalQueueIndex); // 从原始队列中恢复当前歌曲

            if (currentPlayMode == Constants.PLAY_MODE_SHUFFLE) {
                // 找到当前歌曲在随机队列中的位置
                currentQueueIndex = INVALID_INDEX;
                for (int i = 0; i < shuffledPlayQueue.size(); i++) {
                    if (shuffledPlayQueue.get(i).getId() == currentSong.getId()) {
                        currentQueueIndex = i;
                        break;
                    }
                }
                if (currentQueueIndex == INVALID_INDEX) { // 如果在随机队列中找不到，可能随机队列已变，重置
                    Timber.w("Last played song not found in loaded shuffled queue. Resetting shuffle index.");
                    if (!shuffledPlayQueue.isEmpty()) currentQueueIndex = 0; // 或者尝试播放随机队列的第一个
                    else currentSong = null; // 如果随机队列为空，则无法恢复
                }
            } else {
                currentQueueIndex = lastOriginalQueueIndex; // 非随机模式，索引直接对应原始队列
            }

            if (currentSong != null && exoPlayer != null) {
                Uri songUri = Uri.fromFile(new File(currentSong.getPath()));
                MediaItem mediaItem = MediaItem.fromUri(songUri);
                exoPlayer.setMediaItem(mediaItem);
                exoPlayer.prepare();
                exoPlayer.seekTo(lastPosition); // 恢复上次的播放位置
                updateMediaSessionMetadata();
                // 不立即播放，等待用户操作或UI指令
                Timber.d("Playback state loaded. Song: %s, Mode: %d, Index: %d, Position: %dms",
                        currentSong.getTitle(), currentPlayMode, currentQueueIndex, lastPosition);
            }
        } else {
            currentSong = null;
            currentQueueIndex = INVALID_INDEX;
            Timber.d("No valid previous playback state to load or queue is empty.");
        }
        // LiveData 会在 onCreate 结束时或通过 updateCurrentPlaybackInfo 更新
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Timber.d("MediaPlayerService onDestroy");
        saveQueueStateToPrefs(); // 服务销毁前保存最后的状态
        if (progressHandler != null && progressUpdater != null) {
            progressHandler.removeCallbacksAndMessages(null);
        }
        if (exoPlayer != null) {
            exoPlayer.removeListener(this);
            exoPlayer.release();
            exoPlayer = null;
        }
        if (mediaSession != null) {
            mediaSession.release();
            mediaSession = null;
        }
        releaseWakeLock();
        _playbackInfo.postValue(new PlaybackInfo(null, false, 0, 0, "服务已停止", currentPlayMode));
        Timber.i("MediaPlayerService destroyed and resources released.");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Timber.d("MediaPlayerService onBind");
        return binder;
    }

    public static class PlaybackInfo {
        public final Song song;                 // 当前歌曲对象
        public final boolean isPlaying;         // 是否正在播放
        public final long currentPositionMs;   // 当前播放进度 (毫秒)
        public final long durationMs;          // 歌曲总时长 (毫秒)
        public final String errorMessage;        // 播放错误信息 (如果有)
        public final int playMode;              // 当前播放模式
        public final List<Song> activeQueue;     // 当前活动的播放队列 (不可修改的副本或新列表)

        // 主构造函数
        public PlaybackInfo(Song song, boolean isPlaying, long currentPositionMs, long durationMs, String errorMessage, int playMode, List<Song> activeQueue) {
            this.song = song;
            this.isPlaying = isPlaying;
            this.currentPositionMs = currentPositionMs;
            this.durationMs = durationMs;
            this.errorMessage = errorMessage;
            this.playMode = playMode;
            this.activeQueue = activeQueue != null ? Collections.unmodifiableList(new ArrayList<>(activeQueue)) : Collections.emptyList(); // 存储副本并设为不可修改
        }

        // 兼容旧的构造函数，提供默认的空队列
        public PlaybackInfo(Song song, boolean isPlaying, long currentPositionMs, long durationMs, String errorMessage, int playMode) {
            this(song, isPlaying, currentPositionMs, durationMs, errorMessage, playMode, Collections.emptyList());
        }

        // 更早的构造函数，提供默认播放模式和空队列
        public PlaybackInfo(Song song, boolean isPlaying, long currentPositionMs, long durationMs, String errorMessage) {
            this(song, isPlaying, currentPositionMs, durationMs, errorMessage, Constants.PLAY_MODE_ORDER, Collections.emptyList());
        }


        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            PlaybackInfo that = (PlaybackInfo) o;
            return isPlaying == that.isPlaying &&
//                    currentPositionMs == that.currentPositionMs && // 进度比较会导致频繁更新
                    durationMs == that.durationMs &&
                    playMode == that.playMode &&
                    Objects.equals(song, that.song) &&
                    Objects.equals(errorMessage, that.errorMessage) &&
                    Objects.equals(activeQueue, that.activeQueue); // <--- 新增比较 (List.equals 是内容比较)
        }

        @Override
        public int hashCode() {
            return Objects.hash(song, isPlaying, currentPositionMs, durationMs, errorMessage, playMode, activeQueue); // <--- 新增
        }

        @NonNull
        @Override
        public String toString() { // 更新 toString
            return "PlaybackInfo{" +
                    "song=" + (song != null ? song.getTitle() : "null") +
                    ", isPlaying=" + isPlaying +
                    ", currentPositionMs=" + currentPositionMs +
                    ", durationMs=" + durationMs +
                    ", playMode=" + playMode +
                    ", activeQueueSize=" + (activeQueue != null ? activeQueue.size() : 0) +
                    (errorMessage != null ? ", error='" + errorMessage + '\'' : "") +
                    '}';
        }
    }

    public class LocalBinder extends Binder {
        public MediaPlayerService getService() {
            return MediaPlayerService.this;
        }
    }
}